package stockcontrol;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Paint;
import java.text.NumberFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Vector;
import javax.persistence.EntityManager;
import javax.swing.JFrame;
import javax.swing.JTable;
import javax.swing.RowSorter;
import javax.swing.RowSorter.SortKey;
import javax.swing.SortOrder;
import javax.swing.border.TitledBorder;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableRowSorter;
import org.jfree.chart.ChartFactory;
import org.jfree.chart.ChartPanel;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.axis.CategoryAxis;
import org.jfree.chart.axis.CategoryLabelPositions;
import org.jfree.chart.axis.NumberAxis;
import org.jfree.chart.labels.ItemLabelAnchor;
import org.jfree.chart.labels.ItemLabelPosition;
import org.jfree.chart.plot.CategoryPlot;
import org.jfree.chart.plot.DatasetRenderingOrder;
import org.jfree.chart.plot.PlotOrientation;
import org.jfree.chart.renderer.category.BarRenderer;
import org.jfree.chart.renderer.category.CategoryItemRenderer;
import org.jfree.chart.renderer.category.LineAndShapeRenderer;
import org.jfree.data.DataUtilities;
import org.jfree.data.DefaultKeyedValues;
import org.jfree.data.KeyedValues;
import org.jfree.data.category.CategoryDataset;
import org.jfree.data.general.DatasetUtilities;
import org.jfree.ui.TextAnchor;

/**
 *
 * @author yue
 */
public class ParetoForm extends javax.swing.JFrame {


    private Vector nivelA = new Vector();
    private Vector nivelB = new Vector();
    private Vector nivelC = new Vector();

    private void addToNivelA(String art) {
        nivelA.addElement(art);
    }

    private void addToNivelB(String art) {
        nivelB.addElement(art);
    }

    private void addToNivelC(String art) {
        nivelC.addElement(art);
    }

    public Vector<String> getArticulosNivelA(){
        Vector<String> els = new Vector<String>(nivelA.size());
        for (int i = 0; i < nivelA.size(); i++) {
            Vector v = (Vector) nivelA.elementAt(i);
            els.add((String) v.elementAt(0));
        }
        return els;
    }
    public Vector<String> getArticulosNivelB(){
        Vector<String> els = new Vector<String>(nivelB.size());
        for (int i = 0; i < nivelB.size(); i++) {
            Vector v = (Vector) nivelB.elementAt(i);
            els.add((String) v.elementAt(0));
        }
        return els;
    }
    public Vector<String> getArticulosNivelC(){
        Vector<String> els = new Vector<String>(nivelC.size());
        for (int i = 0; i < nivelC.size(); i++) {
            Vector v = (Vector) nivelC.elementAt(i);
            els.add((String) v.elementAt(0));
        }
        return els;
    }

    class wsCellRenderer extends DefaultTableCellRenderer {

        @Override
        public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int col) {
            Component comp = super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, col);
            float p = ((Float) table.getModel().getValueAt(row, 5)).floatValue();
            if (p <= 0.8) 
                comp.setBackground(Color.YELLOW);
            if (p > 0.8 && p <= 0.9)
                comp.setBackground(Color.ORANGE);
            if (p > 0.9)
                comp.setBackground(Color.CYAN);         
            return (comp);
        }
    }

    private String findArtVendidosCat = "SELECT COUNT(*) FROM Articulo a, Venta v WHERE a.codigo=v.articulo and a.codigo_cat=:categoria";
    private String findPareto = "SELECT a.descrip, (SELECT COUNT(*) FROM Articulo a1, Venta v WHERE a.codigo=a1.codigo and a1.codigo=v.articulo)* :demanda / :total_categoria, a.precio FROM Articulo a WHERE a.codigo_cat=:categoria";

    private int nroCategoria;
    private double demanda;

    EntityManager entityManager;
    
    /** Creates new form ParetoForm */
    public ParetoForm(int nroCategoria, double demanda, EntityManager em) {
        entityManager = em;
        initComponents();
        this.setNroCategoria(nroCategoria);
        this.setDemanda(demanda);
        cargarTable();
    }

    public int getNroCategoria() {
        return nroCategoria;
    }

    public void setNroCategoria(int nroCategoria) {
        this.nroCategoria = nroCategoria;
    }

    public double getDemanda() {
        return demanda;
    }

    public void setDemanda(double  demanda) {
        this.demanda = demanda;
    }

    private Vector<Float> getDemandaAnual(List l){
        Vector<Float> d = new Vector<Float>(l.size());
        for (int i = 0; i < l.size(); i++) {
            Object[] tupla = (Object[]) l.get(i);
            Integer demandaMensual = (Integer) tupla[1];
            Float precioUnitario = Float.parseFloat(tupla[1].toString());
            Float demandaAnual = demandaMensual * 12 * precioUnitario;
            d.add( demandaAnual );
        }
        return d;
    }

    private Vector getDemandaAnualAcum(List l){
        Vector d = getDemandaAnual(l);
        Vector acum = new Vector(d.size());
        Integer demandaAnual = (Integer) d.elementAt(0);
        acum.add( demandaAnual );
        for (int i = 1; i < d.size(); i++) {
            demandaAnual = (Integer) acum.elementAt(i-1) + (Integer) d.elementAt(i);
            acum.add( demandaAnual );
        }
        Collections.sort(acum);
        return acum;
    }

    private Vector getDemandaAnualPercent(List l){
        Vector d = getDemandaAnualAcum(l);
        Vector percent = new Vector(d.size());
        for (int i = 1; i < d.size(); i++) {
            Float valor = (Float) d.elementAt(0) / (Float)d.elementAt(d.size()-1);
            percent.add( d );
        }
        return percent;
    }

    public Vector getArtDemandaPrecio(){
        int total_categoria = Integer.parseInt(entityManager.createNativeQuery(findArtVendidosCat)
                    .setParameter("categoria", this.getNroCategoria() ).getSingleResult().toString());

        List l = entityManager.createNativeQuery(findPareto)
                    .setParameter("demanda", this.getDemanda() ).setParameter("total_categoria", total_categoria).setParameter("categoria", this.getNroCategoria() ).getResultList();
        return new Vector(l);
    }

    public Vector getNivelA() {
        return nivelA;
    }

    public void setNivelA(Vector nivelA) {
        this.nivelA = nivelA;
    }

    public Vector getNivelB() {
        return nivelB;
    }

    public void setNivelB(Vector nivelB) {
        this.nivelB = nivelB;
    }

    public Vector getNivelC() {
        return nivelC;
    }

    public void setNivelC(Vector nivelC) {
        this.nivelC = nivelC;
    }

    class CustomRenderer extends BarRenderer {

        /** The colors. */
        private Paint[] colors;

        /**
         * Creates a new renderer.
         *
         * @param colors  the colors.
         */
        public CustomRenderer(final Paint[] colors) {
            this.colors = colors;
        }

        /**
         * Returns the paint for an item.  Overrides the default behaviour inherited from
         * AbstractSeriesRenderer.
         *
         * @param row  the series.
         * @param column  the category.
         *
         * @return The item color.
         */
        @Override
        public Paint getItemPaint(final int row, final int column) {
            int a = getNivelA().size();
            int b = getNivelB().size();


            if (column < a){
                return Color.YELLOW;
            } else
            if (column >= a && column < a+b){
                return Color.ORANGE;
            } else
                return Color.CYAN;

        }
    }

    void graficar(){
        final DefaultKeyedValues data = new DefaultKeyedValues();
        
        int size = jTable.getRowCount();
        for (int i = 0; i < size; i++) {
            String articulo = (String) jTable.getValueAt(i, 0);
            Float demAnual = (Float) jTable.getValueAt(i, 3);
            if ( demAnual > 0 )
                data.addValue(articulo.trim(), demAnual);
        }
        
        data.sortByValues(org.jfree.util.SortOrder.DESCENDING);
        final KeyedValues cumulative = DataUtilities.getCumulativePercentages(data);
        final CategoryDataset dataset = DatasetUtilities.createCategoryDataset("Articulos", data);
        // create the chart...
        final JFreeChart chart = ChartFactory.createBarChart(
            "Articulos importantes ABC - Pareto",   // chart title
            "Articulos",                            // domain axis label
            "Demanda Anual en Pesos",                  // range axis label
            dataset,                                // data
            PlotOrientation.VERTICAL,
            true,                                   // include legend
            true,
            false
        );

        // set the background color for the chart...
        chart.setBackgroundPaint(Color.WHITE);

        // get a reference to the plot for further customisation...
        final CategoryPlot plot = chart.getCategoryPlot();

        final CategoryAxis domainAxis = plot.getDomainAxis();
        domainAxis.setLowerMargin(0.02);
        domainAxis.setUpperMargin(0.02);

        domainAxis.setCategoryLabelPositions(CategoryLabelPositions.UP_45);

        // set the range axis to display integers only...
        final NumberAxis rangeAxis = (NumberAxis) plot.getRangeAxis();
        rangeAxis.setStandardTickUnits(NumberAxis.createIntegerTickUnits());

        final LineAndShapeRenderer renderer2 = new LineAndShapeRenderer();

        final CategoryDataset dataset2 = DatasetUtilities.createCategoryDataset(
            "Acumulada", cumulative
        );

        final NumberAxis axis2 = new NumberAxis("Procentaje");
        axis2.setNumberFormatOverride(NumberFormat.getPercentInstance());
        plot.setRangeAxis(1, axis2);
        plot.setDataset(1, dataset2);
        plot.setRenderer(1, renderer2);
        plot.mapDatasetToRangeAxis(1, 1);

        plot.setDatasetRenderingOrder(DatasetRenderingOrder.REVERSE);
        // OPTIONAL CUSTOMISATION COMPLETED.
        
        final CategoryItemRenderer renderer = new CustomRenderer(
            new Paint[] {Color.yellow, Color.orange, Color.cyan}
        );

        //renderer.setLabelGenerator(new StandardCategoryLabelGenerator());
        renderer.setItemLabelsVisible(true);
        final ItemLabelPosition p = new ItemLabelPosition(
            ItemLabelAnchor.CENTER, TextAnchor.CENTER, TextAnchor.CENTER, 45.0
        );
        renderer.setPositiveItemLabelPosition(p);
        plot.setRenderer(renderer);

        // add the chart to a panel...
        ChartPanel chartPanel = new ChartPanel(chart);

        jPanel1.setLayout(new BorderLayout());
        jPanel1.add(chartPanel, BorderLayout.CENTER);
        chartPanel.setSize(jPanel1.getSize());
        jPanel1.setBorder(new TitledBorder("Resultado") );
    }
    
    
    void cargarTable(){       
        Vector v = this.getArtDemandaPrecio();
        DefaultTableModel tableModel = (DefaultTableModel) jTable.getModel();
        
        int filas = v.size();
        int columnas = 6;
        tableModel.setRowCount(filas);
        DefaultTableModel newModel = new DefaultTableModel(filas, columnas);
        String[] titulos = {"Articulo", "Demanda Anual", "Precio Unitario", "Valor Demanda Anual","Valor Demanda Anual Acum", "%VAL" };
        newModel.setColumnIdentifiers(titulos);


        for (int i = 0; i < filas; i++) {
            Object[] tupla = (Object[]) v.elementAt(i);
            String art = ((String) tupla[0]).trim();
            Integer d = (Integer) tupla[1];
            Float precio = Float.parseFloat(tupla[2].toString());
            Float val = d.floatValue() * precio;

            tableModel.setValueAt(art, i, 0);
            tableModel.setValueAt(d, i, 1);
            tableModel.setValueAt(precio, i, 2);
            tableModel.setValueAt(val, i, 3);           
        }
        
        TableRowSorter sorter = new TableRowSorter(tableModel);
        List <RowSorter.SortKey> sortKeys
            = new ArrayList<RowSorter.SortKey>();
        sortKeys.add(new SortKey(3, SortOrder.DESCENDING));
        sorter.setSortKeys(sortKeys);

        
        jTable.setModel(tableModel);
        jTable.setRowSorter(sorter);
    
        Float valAcum = new Float(0.0);
        
        //actualizar el modelo
        for (int i = 0; i < filas; i++)
            for (int j = 0; j < columnas; j++) 
                newModel.setValueAt(jTable.getValueAt(i, j), i, j); 
        
        for (int i = 0; i < filas; i++) {
            valAcum += (Float) newModel.getValueAt(i, 3);
            newModel.setValueAt(valAcum, i, 4);
        }

        Float max = (Float) newModel.getValueAt(v.size()-1, 4);
        for (int i = 0; i < v.size(); i++) {
            Float porcentaje = (Float) newModel.getValueAt(i, 4) / (Float)max;
            newModel.setValueAt(porcentaje, i, 5);
            float p =  porcentaje.floatValue();
            if (p <= 0.8){
                String art = (String) newModel.getValueAt(i,0);
                this.addToNivelA(art);
                System.out.println("A - " + art);
            }
            if (p > 0.8 && p <= 0.9)
                addToNivelB((String) newModel.getValueAt(i,0));
            if (p > 0.9)
                addToNivelC((String) newModel.getValueAt(i,0));
        }
        jTable.setModel(newModel);
        jTable.setDefaultRenderer(Object.class, new wsCellRenderer());

        jTable.setRowSorter(null);
        
        graficar();
    }

    /** This method is called from within the constructor to
     * initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is
     * always regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        jScrollPane1 = new javax.swing.JScrollPane();
        jTable = new javax.swing.JTable();
        jPanel1 = new javax.swing.JPanel();
        jXLabel1 = new org.jdesktop.swingx.JXLabel();

        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
        org.jdesktop.application.ResourceMap resourceMap = org.jdesktop.application.Application.getInstance(stockcontrol.StockControlApp.class).getContext().getResourceMap(ParetoForm.class);
        setTitle(resourceMap.getString("Form.title")); // NOI18N
        setName("Form"); // NOI18N

        jScrollPane1.setName("jScrollPane1"); // NOI18N

        jTable.setModel(new javax.swing.table.DefaultTableModel(
            new Object [][] {
                {null, null, null, null, null, null},
                {null, null, null, null, null, null},
                {null, null, null, null, null, null},
                {null, null, null, null, null, null}
            },
            new String [] {
                "Articulo", "Demanda Anual", "Precio Unitario", "Valor Demanda Anual", "Valor Demanda Anual Acum", "% VAL"
            }
        ) {
            Class[] types = new Class [] {
                java.lang.String.class, java.lang.Integer.class, java.lang.Float.class, java.lang.Float.class, java.lang.Float.class, java.lang.Float.class
            };
            boolean[] canEdit = new boolean [] {
                false, false, false, false, false, false
            };

            public Class getColumnClass(int columnIndex) {
                return types [columnIndex];
            }

            public boolean isCellEditable(int rowIndex, int columnIndex) {
                return canEdit [columnIndex];
            }
        });
        jTable.setEnabled(false);
        jTable.setName("jTable"); // NOI18N
        jScrollPane1.setViewportView(jTable);

        jPanel1.setBorder(javax.swing.BorderFactory.createTitledBorder(resourceMap.getString("jPanel1.border.title"))); // NOI18N
        jPanel1.setName("jPanel1"); // NOI18N

        javax.swing.GroupLayout jPanel1Layout = new javax.swing.GroupLayout(jPanel1);
        jPanel1.setLayout(jPanel1Layout);
        jPanel1Layout.setHorizontalGroup(
            jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGap(0, 368, Short.MAX_VALUE)
        );
        jPanel1Layout.setVerticalGroup(
            jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGap(0, 104, Short.MAX_VALUE)
        );

        jXLabel1.setHorizontalAlignment(javax.swing.SwingConstants.CENTER);
        jXLabel1.setLineWrap(true);
        jXLabel1.setText(resourceMap.getString("jXLabel1.text")); // NOI18N
        jXLabel1.setName("jXLabel1"); // NOI18N

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
                    .addComponent(jXLabel1, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, 764, Short.MAX_VALUE)
                    .addGroup(layout.createSequentialGroup()
                        .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 378, Short.MAX_VALUE)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(jPanel1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)))
                .addContainerGap())
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addContainerGap()
                .addComponent(jXLabel1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
                    .addComponent(jPanel1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                    .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 131, Short.MAX_VALUE))
                .addContainerGap())
        );

        pack();
    }// </editor-fold>//GEN-END:initComponents

    /**
    * @param args the command line arguments
    */
    public static void main(String args[]) {
        java.awt.EventQueue.invokeLater(new Runnable() {
            public void run() {
               // new ParetoForm().setVisible(true);
            }
        });
    }

    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JPanel jPanel1;
    private javax.swing.JScrollPane jScrollPane1;
    private javax.swing.JTable jTable;
    private org.jdesktop.swingx.JXLabel jXLabel1;
    // End of variables declaration//GEN-END:variables

}
